home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
-
- bwb_exp.c Expression Parser
- for Bywater BASIC Interpreter
-
- Copyright (c) 1992, Ted A. Campbell
-
- Bywater Software
- P. O. Box 4023
- Duke Station
- Durham, NC 27706
-
- email: tcamp@acpub.duke.edu
-
- Copyright and Permissions Information:
-
- All U.S. and international copyrights are claimed by the
- author. The author grants permission to use this code
- and software based on it under the following conditions:
- (a) in general, the code and software based upon it may be
- used by individuals and by non-profit organizations; (b) it
- may also be utilized by governmental agencies in any country,
- with the exception of military agencies; (c) the code and/or
- software based upon it may not be sold for a profit without
- an explicit and specific permission from the author, except
- that a minimal fee may be charged for media on which it is
- copied, and for copying and handling; (d) the code must be
- distributed in the form in which it has been released by the
- author; and (e) the code and software based upon it may not
- be used for illegal activities.
-
- ****************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
-
- #include "bwbasic.h"
- #include "bwb_mes.h"
-
- int exp_esc = 0; /* expression stack counter */
-
- /***************************************************************
-
- FUNCTION: bwb_exp()
-
- DESCRIPTION: This is the function by which the expression
- parser is called.
-
- ***************************************************************/
-
- struct exp_ese *
- bwb_exp( char *expression, int assignment, int *position )
- {
- struct exp_ese *rval; /* return value */
- int entry_level, main_loop, adv_loop, err_condition;
- char *e; /* pointer to current string */
- int r; /* return value from functions */
- register int c; /* quick counter */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): expression <%s> assignment <%d> level <%d>",
- & ( expression[ *position ] ), assignment, exp_esc );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* save the entry level of the expression stack in order to
- check it at the end of this function */
-
- entry_level = exp_esc;
- err_condition = FALSE;
-
- /* advance past whitespace or beginningg of line segment */
-
- if ( expression[ *position ] == ':' )
- {
- ++( *position );
- }
- adv_ws( expression, position );
- if ( expression[ *position ] == ':' )
- {
- ++( *position );
- adv_ws( expression, position );
- }
-
- /* increment the expression stack counter to get a new level */
-
- inc_esc();
-
- /* check to be sure there is a legitimate expression
- and set initial parameters for the main loop */
-
- adv_loop = TRUE;
- while( adv_loop == TRUE )
- {
- switch( expression[ *position ] )
- {
- case ' ': /* whitespace */
- case '\t':
- ++(*position);
- break;
- case '\0': /* end of string */
- case '\r':
- case '\n':
- main_loop = adv_loop = FALSE; /* break out of loop */
- break;
- default:
- adv_loop = FALSE;
- main_loop = TRUE;
- exp_es[ exp_esc ].pos_adv = 0;
- break;
- }
- }
-
- /* main parsing loop */
-
- while ( main_loop == TRUE )
- {
-
- /* set variable <e> to the start of the expression */
-
- e = &( expression[ *position ] );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): main loop, level <%d> element <%s> ",
- exp_esc, e );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* detect the operation required at this level */
-
- exp_es[ exp_esc ].operation = exp_findop( e );
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): exp_findop() returned <%d>",
- exp_es[ exp_esc ].operation );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* perform actions specific to the operation */
-
- switch( exp_es[ exp_esc ].operation )
- {
- case OP_ERROR:
- main_loop = FALSE;
- err_condition = TRUE;
- break;
- case OP_TERMINATE:
- main_loop = FALSE;
- /* *position += 1; */
- dec_esc();
- break;
- case OP_STRJOIN: /* string join or tab */
- case OP_STRTAB:
- main_loop = FALSE;
- dec_esc();
- break;
- case OP_ADD: /* in the case of any numerical operation, */
- case OP_SUBTRACT:
- case OP_MULTIPLY:
- case OP_DIVIDE:
- case OP_MODULUS:
- case OP_EXPONENT:
- case OP_INTDIVISION:
- case OP_GREATERTHAN:
- case OP_LESSTHAN:
- case OP_GTEQ:
- case OP_LTEQ:
- case OP_NOTEQUAL:
- case OP_NOT:
- case OP_AND:
- case OP_OR:
- case OP_XOR:
- case OP_IMPLIES:
- case OP_EQUIV:
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): operator detected." );
- bwb_debug( bwb_ebuf );
- #endif
-
- exp_es[ exp_esc ].pos_adv = -1; /* set to strange number */
-
- /* cycle through operator table to find match */
-
- for ( c = 0; c < N_OPERATORS; ++c )
- {
- if ( exp_ops[ c ].operation == exp_es[ exp_esc ].operation )
- {
- exp_es[ exp_esc ].pos_adv = strlen( exp_ops[ c ].symbol );
- }
- }
-
- if ( exp_es[ exp_esc ].pos_adv == -1 ) /* was a match found? */
- {
- exp_es[ exp_esc ].pos_adv = 0; /* no -- set to 0 */
- }
- break; /* and move on */
-
- case OP_EQUALS:
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): equal sign detected." );
- bwb_debug( bwb_ebuf );
- #endif
-
- if ( assignment == TRUE )
- {
- exp_es[ exp_esc ].operation = OP_ASSIGN;
- }
- exp_es[ exp_esc ].pos_adv = 1;
- break;
-
- case PARENTHESIS:
- r = exp_paren( e );
- break;
- case CONST_STRING:
- r = exp_strconst( e );
- break;
- case CONST_NUMERICAL:
- r = exp_numconst( e );
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): return from exp_numconst(), r = <%d>",
- r );
- bwb_debug( bwb_ebuf );
- #endif
- break;
-
- case FUNCTION:
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): calling exp_function(), expression <%s>",
- e );
- bwb_debug( bwb_ebuf );
- #endif
-
- r = exp_function( e );
- break;
-
- case VARIABLE:
- r = exp_variable( e );
- break;
- default:
- err_condition = TRUE;
- main_loop = FALSE;
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_exp.c:bwb_exp(): unidentified operation (%d).",
- exp_es[ exp_esc ].operation );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- break;
- }
-
- /* increment *position counter based on previous actions */
-
- *position += exp_es[ exp_esc ].pos_adv;
- exp_es[ exp_esc ].pos_adv = 0; /* reset advance counter */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): advanced position; r <%d> err_c <%d>",
- r, err_condition );
- bwb_debug( bwb_ebuf );
- #endif
-
- #if INTENSIVE_DEBUG
- if ( exp_es[ exp_esc ].operation == OP_EQUALS )
- {
- sprintf( bwb_ebuf, "in bwb_exp(): with OP_EQUALS: finished case" );
- bwb_debug( bwb_ebuf );
- }
- #endif
-
- /* check for end of string */
-
- adv_loop = TRUE;
- while( adv_loop == TRUE )
- {
- switch( expression[ *position ] )
- {
- case ' ': /* whitespace */
- case '\t':
- ++(*position);
- break;
- case '\0': /* end of string */
- case '\r':
- case '\n':
- case ':':
- main_loop = adv_loop = FALSE; /* break out of loop */
- break;
- default:
- adv_loop = FALSE;
- break;
- }
- }
-
- /* get a new stack level before looping */
-
- if ( main_loop == TRUE )
- {
- r = inc_esc();
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): increment esc, r <%d>, err_c <%d>",
- r, err_condition );
- bwb_debug( bwb_ebuf );
- #endif
- }
-
- /* check for error return */
-
- if ( r == OP_ERROR )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): found r == OP_ERROR." );
- bwb_debug( bwb_ebuf );
- #endif
- main_loop = FALSE;
- err_condition = TRUE;
- }
- else
- {
- r = TRUE;
- }
-
- } /* end of main parsing loop */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): breakout from main parsing loop, r <%d> err_c <%d>",
- r, err_condition );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* check error condition */
-
- if ( err_condition == TRUE )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "ERROR: error detected in expression parser" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* decrement the expression stack counter until it matches entry_level */
-
- while( exp_esc > entry_level )
- {
- dec_esc();
- }
-
- }
-
- /* no error; normal exit from function */
-
- else
- {
-
- /* are any more operations needed? if we are still at entry level,
- then they are not */
-
- /* try operations */
-
- exp_operation( entry_level );
-
- /* see what is on top of the stack */
-
- if ( exp_esc > ( entry_level + 1 ))
- {
- switch( exp_es[ exp_esc ].operation )
- {
- case OP_STRJOIN:
- if ( exp_esc != ( entry_level + 2 ))
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_exp(): OP_STRJOIN in wrong position." );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- }
- break;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_exp(): incomplete expression." );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- break;
- }
-
- /* decrement the expression stack counter */
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in bwb_exp(): before dec_esc type is <%c>",
- exp_es[ exp_esc ].type );
- bwb_debug( bwb_ebuf );
- #endif
-
- dec_esc();
-
- }
-
- /* assign rvar to the variable for the current level */
-
- rval = &( exp_es[ exp_esc ] );
-
- /* decrement the expression stack counter */
-
- dec_esc();
-
- /* check the current level before exit */
-
- if ( entry_level != exp_esc )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in bwb_exp(): exit stack level (%d) does not match entry stack level (%d)",
- exp_esc, entry_level );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_overflow );
- #endif
- }
-
- }
-
- /* return a pointer to the last stack level */
-
- return rval;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_findop()
-
- DESCRIPTION: This function reads the expression to find
- what operation is required at its stack level.
-
- ***************************************************************/
-
- int
- exp_findop( char *expression )
- {
- char *pointer; /* pointer to start of string */
- register int c; /* character counter */
- int carry_on; /* boolean: control while loop */
- int rval; /* return value */
- char tbuf[ MAXSTRINGSIZE + 1 ];
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_findop(): received <%s>", expression );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* set return value to OP_NULL initially */
-
- rval = OP_NULL;
-
- /* assign local pointer to expression to begin reading */
-
- pointer = expression;
-
- /* advance to the first significant character */
-
- carry_on = TRUE;
- while ( carry_on == TRUE )
- {
- switch( *pointer )
- {
- case ' ': /* whitespace */
- case '\t':
- ++pointer; /* increment the pointer */
- break; /* and move on */
- default:
- carry_on = FALSE; /* break out of while loop */
- break;
- }
- }
-
- /* we now have the first significant character and can begin parsing */
-
- /* check the first character for an indication of a parenthetical
- expression, a string constant, or a numerical constant that begins
- with a digit (numerical constants beginning with a plus or minus
- sign or hex/octal/binary constants will have to be detected by
- exp_isnc() */
-
- carry_on = TRUE;
- switch ( *pointer )
- {
- case '\"': /* this should indicate a string constant */
- rval = CONST_STRING;
- break;
- case '(': /* this will indicate a simple parenthetical expression */
- rval = PARENTHESIS;
- break;
- case ':': /* terminate processing */
- rval = OP_TERMINATE;
- break;
- case '0': /* these will indicate a numerical constant */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '.':
- case '&': /* designator for hex or octal constant */
- rval = CONST_NUMERICAL;
- break;
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_findop(): rval pos 1 is <%d>", rval );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* string constants, numerical constants, open parentheses, and
- the plus and minus operators have been checked at this point;
- but if the return value is still OP_NULL, other possibilities
- must be checked, namely, other operators, function names, and
- variable names */
-
- /* get a character string to be interpreted */
-
- if ( rval == OP_NULL )
- {
-
- carry_on = TRUE;
- c = 0;
- tbuf[ c ] = *pointer;
- ++c;
- tbuf[ c ] = '\0';
- while( carry_on == TRUE )
- {
- switch( pointer[ c ] )
- {
- case ' ': /* whitespace */
- case '\t':
- case '(':
- case ')':
- case ',':
- case ';':
- case '\0':
- case '\n':
- case '\r':
- carry_on = FALSE;
- break;
- default:
- tbuf[ c ] = pointer[ c ];
- ++c;
- tbuf[ c ] = '\0';
- break;
- }
- }
-
- }
-
- /* check for a BASIC command */
-
- if ( rval == OP_NULL )
- {
- rval = exp_iscmd( tbuf );
- }
-
- /* check for numerical constant */
-
- if ( rval == OP_NULL )
- {
- rval = exp_isnc( tbuf );
- }
-
- /* check for other operators */
-
- if ( rval == OP_NULL )
- {
- rval = exp_isop( tbuf );
- }
-
- /* check for function name */
-
- if ( rval == OP_NULL )
- {
- rval = exp_isfn( tbuf );
- }
-
- /* last: check for variable name, and assign it if there
- is not already one */
-
- if ( rval == OP_NULL )
- {
- rval = exp_isvn( tbuf );
- }
-
- /* return the value assigned (or OP_NULL if none assigned) */
-
- return rval;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_isnc()
-
- DESCRIPTION: This function reads the expression to find
- if a logical or mathematical operation is required at
- this point.
-
- ***************************************************************/
-
- int
- exp_isnc( char *expression )
- {
-
- switch( expression[ 0 ] )
- {
- case '0': /* these will indicate a numerical constant */
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '&': /* indicator for hex or octal constant */
- return CONST_NUMERICAL;
- case '+':
- case '-':
-
- /* if the previous stack level was a numerical value or a string,
- then this is certainly not one; return OP_NULL here
- and let the next function call to exp_isop() determine
- the (plus or minus) operator */
-
- if ( ( exp_es[ exp_esc - 1 ].operation == NUMBER )
- || ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
- || ( exp_es[ exp_esc - 1 ].operation == CONST_STRING ) )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_isnc(): previous function is a number or string" );
- bwb_debug( bwb_ebuf );
- #endif
-
- return OP_NULL;
- }
-
- /* similarly, if the previous stack level was a variable
- with a numerical value (not a string), then this level
- must be an operator, not a numerical constant */
-
- if ( ( exp_es[ exp_esc - 1 ].operation == VARIABLE )
- && ( exp_es[ exp_esc - 1 ].type != STRING ))
- {
- return OP_NULL;
- }
-
- /* failing these tests, the argument must be a numerical
- constant preceded by a plus or minus sign */
-
- return CONST_NUMERICAL;
-
- default:
- return OP_NULL;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_isop()
-
- DESCRIPTION: This function reads the expression to find
- if a logical or mathematical operation is required at
- this point.
-
- This function presupposes that a numerical constant with
- affixed plus or minus sign has been ruled out.
-
- ***************************************************************/
-
- int
- exp_isop( char *expression )
- {
- register int c; /* counter */
- char tbuf[ MAXSTRINGSIZE + 1 ];
-
- /* first convert the expression to upper-case so that comparisons
- will work */
-
- for ( c = 0; expression[ c ] != '\0'; ++c )
- {
- if ( islower( expression[ c ] ))
- {
- tbuf[ c ] = toupper( expression[ c ] );
- }
- else
- {
- tbuf[ c ] = expression[ c ];
- }
- tbuf[ c + 1 ] = '\0';
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_isop(): expression is <%s>", tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* compare the initial characters of the string with the table
- of operators */
-
- for ( c = 0; c < N_OPERATORS; ++c )
- {
- if ( strncmp( tbuf, exp_ops[ c ].symbol,
- (size_t) strlen( exp_ops[ c ].symbol ) ) == 0 )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_isop(): match <%s>, number <%d>.",
- exp_ops[ c ].symbol, c );
- bwb_debug( bwb_ebuf );
- #endif
-
- return exp_ops[ c ].operation;
- }
- }
-
- /* search failed; return OP_NULL */
-
- return OP_NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_iscmd()
-
- DESCRIPTION: This function reads the expression to find
- if a BASIC command name is present; if so, it returns
- OP_TERMINATE to terminate expression parsing. This is
- critical, for example, in parsing a conditional following
- IF where THEN, ELSE, and other BASIC commands may follow.
-
- ***************************************************************/
-
- int
- exp_iscmd( char *expression )
- {
- register int n;
- char tbuf[ MAXSTRINGSIZE + 1 ];
-
- /* capitalize the expression */
-
- for ( n = 0; expression[ n ] != '\0'; ++n )
- {
- if ( n >= MAXARGSIZE )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "Maximum arguments size exceeded." );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_overflow );
- #endif
- }
- if ( islower( expression[ n ] ) != FALSE )
- {
- tbuf[ n ] = toupper( expression[ n ] );
- }
- else
- {
- tbuf[ n ] = expression[ n ];
- }
- tbuf[ n + 1 ] = '\0';
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_iscmd(): expression received <%s>, converted <%s>.",
- expression, tbuf );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* first check for THEN or ELSE statements */
-
- if ( strcmp( tbuf, "THEN" ) == 0 )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
- return OP_TERMINATE;
- }
-
- if ( strcmp( tbuf, "ELSE" ) == 0 )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
- return OP_TERMINATE;
- }
-
- /* run through the command table and search for a match */
-
- for ( n = 0; n < COMMANDS; ++n )
- {
- if ( strcmp( tbuf, bwb_cmdtable[ n ].name ) == 0 )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_iscmd(): match found, <%s>",
- tbuf );
- bwb_debug( bwb_ebuf );
- #endif
- return OP_TERMINATE;
- }
- #if INTENSIVE_DEBUG
- else
- {
- sprintf( bwb_ebuf, "in exp_iscmd(): No match, <%s> and <%s>; returns %d",
- tbuf, bwb_cmdtable[ n ].name,
- strcmp( tbuf, bwb_cmdtable[ n ].name ) );
- bwb_debug( bwb_ebuf );
- }
- #endif
- }
-
- /* search failed, return NULL */
-
- return OP_NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_isfn()
-
- DESCRIPTION: This function reads the expression to find
- if a function name is present at this point.
-
- ***************************************************************/
-
- int
- exp_isfn( char *expression )
- {
-
- if ( fnc_find( expression ) == NULL )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_isfn(): failed to find function <%s>",
- expression );
- bwb_debug( bwb_ebuf );
- #endif
- return OP_NULL;
- }
- else
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_isfn(): found function <%s>",
- expression );
- bwb_debug( bwb_ebuf );
- #endif
- return FUNCTION;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_isvn()
-
- DESCRIPTION: This function reads the expression to find
- if a variable name at this point.
-
- ***************************************************************/
-
- int
- exp_isvn( char *expression )
- {
-
- exp_getvfname( expression, exp_es[ exp_esc ].string );
-
- if ( var_find( exp_es[ exp_esc ].string ) == NULL )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_isvn(): failed to find variable <%s>",
- expression );
- bwb_debug( bwb_ebuf );
- #endif
- return OP_NULL;
- }
- else
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_isvn(): found variable <%s>",
- exp_es[ exp_esc ].string );
- bwb_debug( bwb_ebuf );
- #endif
- return VARIABLE;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_getvfname()
-
- DESCRIPTION: This function reads the expression to find
- a variable or function name at this point.
-
- ***************************************************************/
-
- int
- exp_getvfname( char *source, char *destination )
- {
- int s_pos, d_pos; /* source, destination positions */
-
- s_pos = d_pos = 0;
- destination[ 0 ] = '\0';
- while( source[ s_pos ] != '\0' )
- {
-
- /* all aphabetical characters are acceptable */
-
- if ( isalpha( source[ s_pos ] ) != 0 )
-
- {
- destination[ d_pos ] = source[ s_pos ];
-
- ++d_pos;
- ++s_pos;
- destination[ d_pos ] = '\0';
- }
-
- /* numerical characters are acceptable but not in the first position */
-
- else if (( isdigit( source[ s_pos ] ) != 0 ) && ( d_pos != 0 ))
- {
- destination[ d_pos ] = source[ s_pos ];
- ++d_pos;
- ++s_pos;
- destination[ d_pos ] = '\0';
- }
-
- /* other characters will have to be tried on their own merits */
-
- else
- {
- switch( source[ s_pos ] )
- {
-
- case '.': /* tolerated non-alphabetical characters */
-
- case '_':
- destination[ d_pos ] = source[ s_pos ];
- ++d_pos;
- ++s_pos;
- destination[ d_pos ] = '\0';
- break;
-
- case STRING: /* terminating characters */
- case SINGLE:
- case DOUBLE:
- case INTEGER:
- destination[ d_pos ] = source[ s_pos ];
- ++d_pos;
- ++s_pos;
- destination[ d_pos ] = '\0';
-
- return TRUE;
- default: /* anything else is non-tolerated */
- return FALSE;
- }
- }
- }
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getvfname(): found name <%s>", destination );
- bwb_debug( bwb_ebuf );
- #endif
-
- return TRUE; /* exit after coming to the end */
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_validarg()
-
- DESCRIPTION: This function reads the expression to
- determine whether it is a valid argument (to be
- read recursively by bwb_exp() and passed to a
- function.
-
- ***************************************************************/
-
- int
- exp_validarg( char *expression )
- {
- register int c;
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_validarg(): expression <%s>.",
- expression );
- bwb_debug( bwb_ebuf );
- #endif
-
- c = 0;
- while ( TRUE )
- {
- switch( expression[ c ] )
- {
- case ' ':
- case '\t':
- ++c;
- break;
- case '\0':
- return FALSE;
- default:
- return TRUE;
- }
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_getdval()
-
- DESCRIPTION:
-
- ***************************************************************/
-
- double
- exp_getdval( struct exp_ese *e )
- {
-
- /* check for variable */
-
- if ( e->operation == VARIABLE )
- {
- switch( e->type )
- {
- case DOUBLE:
- return (* var_finddval( e->xvar, e->array_pos ));
- case SINGLE:
- return (double) (* var_findfval( e->xvar, e->array_pos ));
- case INTEGER:
- return (double) (* var_findival( e->xvar, e->array_pos ));
- default:
- bwb_error( err_mismatch );
- return (double) 0.0;
- }
- }
-
- /* must be a numerical value */
-
- if ( e->operation != NUMBER )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getdval(): operation <%d> is not a number",
- e->operation );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return (double) 0.0;
- }
-
- /* return specific values */
-
- switch( e->type )
- {
- case SINGLE:
- return (double) e->fval;
- case INTEGER:
- return (double) e->ival;
- case DOUBLE:
- return e->dval;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getdval(): type is <%c>",
- e->type );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return (double) 0.0;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_getfval()
-
- DESCRIPTION:
-
- ***************************************************************/
-
- float
- exp_getfval( struct exp_ese *e )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getfval(): entry" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* check for variable */
-
- if ( e->operation == VARIABLE )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
- bwb_debug( bwb_ebuf );
- #endif
-
- switch( e->type )
- {
- case DOUBLE:
- return (float) (* var_finddval( e->xvar, e->array_pos ));
- case SINGLE:
- return (* var_findfval( e->xvar, e->array_pos ));
- case INTEGER:
- return (float) (* var_findival( e->xvar, e->array_pos ));
- default:
- bwb_error( err_mismatch );
- return (float) 0.0;
- }
- }
-
- /* must be a numerical value */
-
- if ( e->operation != NUMBER )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getfval(): operation <%d> is not a number",
- e->operation );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return (float) 0.0;
- }
-
- /* return specific values */
-
- switch( e->type )
- {
- case SINGLE:
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getfval(): returning from SINGLE, val <%f>",
- e->fval );
- bwb_debug( bwb_ebuf );
- #endif
- return e->fval;
- case INTEGER:
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getfval(): returning from INTEGER, val <%d>",
- e->ival );
- bwb_debug( bwb_ebuf );
- #endif
- return (float) e->ival;
- case DOUBLE:
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getfval(): returning from DOUBLE, val <%lf>",
- e->dval );
- bwb_debug( bwb_ebuf );
- #endif
- return (float) e->dval;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getfval(): type is <%c>",
- e->type );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return (float) 0.0;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_getival()
-
- DESCRIPTION:
-
- ***************************************************************/
-
- int
- exp_getival( struct exp_ese *e )
- {
-
- /* check for variable */
-
- if ( e->operation == VARIABLE )
- {
- switch( e->type )
- {
- case DOUBLE:
- return (int) (* var_finddval( e->xvar, e->array_pos ));
- case SINGLE:
- return (int) (* var_findfval( e->xvar, e->array_pos ));
- case INTEGER:
- return (* var_findival( e->xvar, e->array_pos ));
- default:
- bwb_error( err_mismatch );
- return 0;
- }
- }
-
- /* must be a numerical value */
-
- if ( e->operation != NUMBER )
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getival(): operation <%d> is not a number",
- e->operation );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return 0;
- }
-
- /* return specific values */
-
- switch( e->type )
- {
- case SINGLE:
- return (int) e->fval;
- case INTEGER:
- return e->ival;
- case DOUBLE:
- return (int) e->dval;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getival(): type is <%c>",
- e->type );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return 0;
- }
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_getsval()
-
- DESCRIPTION:
-
- ***************************************************************/
-
- bstring *
- exp_getsval( struct exp_ese *e )
- {
- static bstring b;
- #if TEST_BSTRING
- static int init = FALSE;
-
- if ( init == FALSE )
- {
- sprintf( b.name, "<exp_getsval() bstring>" );
- }
- #endif
-
- b.rab = FALSE;
-
- /* return based on operation type */
-
- switch( e->operation )
- {
- case CONST_STRING:
- case OP_STRJOIN:
- return &( e->sval );
- case VARIABLE:
- switch( e->type )
- {
- case STRING:
- return var_findsval( e->xvar, e->array_pos );
- case DOUBLE:
- sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
- str_ctob( &b, bwb_ebuf );
- return &b;
- case SINGLE:
- sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
- str_ctob( &b, bwb_ebuf );
- return &b;
- case INTEGER:
- sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
- str_ctob( &b, bwb_ebuf );
- return &b;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
- e->type );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return NULL;
- }
- break;
-
- case NUMBER:
- switch( e->type )
- {
- case DOUBLE:
- sprintf( bwb_ebuf, "%lf ", exp_getdval( e ) );
- str_ctob( &b, bwb_ebuf );
- return &b;
- case SINGLE:
- sprintf( bwb_ebuf, "%f ", exp_getfval( e ) );
- str_ctob( &b, bwb_ebuf );
- return &b;
- case INTEGER:
- sprintf( bwb_ebuf, "%d ", exp_getival( e ) );
- str_ctob( &b, bwb_ebuf );
- return &b;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getsval(): type <%c> inappropriate for NUMBER",
- e->type );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return NULL;
- }
- break;
- default:
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_getsval(): operation <%d> inappropriate",
- e->operation );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return NULL;
- }
-
- /* this point may not be reached */
-
- return NULL;
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_findfval()
-
- DESCRIPTION:
-
- ***************************************************************/
-
- #ifdef NO_LONGER_IMPLEMENTED
- float *
- exp_findfval( struct exp_ese *e )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_findfval(): entry" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* check for variable */
-
- if ( e->operation == VARIABLE )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getfval(): returning variable" );
- bwb_debug( bwb_ebuf );
- #endif
- return var_findfval( e->xvar, e->xvar->array_pos );
- }
-
- /* must be a numerical value */
-
- if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_findfval(): operation is not a single-precision number" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return NULL;
- }
-
- /* return specific value */
-
- return &( e->fval );
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_finddval()
-
- DESCRIPTION:
-
- ***************************************************************/
-
- double *
- exp_finddval( struct exp_ese *e )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_finddval(): entry" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* check for variable */
-
- if ( e->operation == VARIABLE )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getdval(): returning variable" );
- bwb_debug( bwb_ebuf );
- #endif
- return var_finddval( e->xvar, e->xvar->array_pos );
- }
-
- /* must be a numerical value */
-
- if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_finddval(): operation is not a double-precision number" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return NULL;
- }
-
- /* return specific value */
-
- return &( e->dval );
-
- }
-
- /***************************************************************
-
- FUNCTION: exp_findival()
-
- DESCRIPTION:
-
- ***************************************************************/
-
- int *
- exp_findival( struct exp_ese *e )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_findival(): entry" );
- bwb_debug( bwb_ebuf );
- #endif
-
- /* check for variable */
-
- if ( e->operation == VARIABLE )
- {
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in exp_getival(): returning variable" );
- bwb_debug( bwb_ebuf );
- #endif
- return var_findival( e->xvar, e->xvar->array_pos );
- }
-
- /* must be a numerical value */
-
- if ( ( e->operation != NUMBER ) && ( e->type != SINGLE ))
- {
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in exp_findival(): operation is not an integer number" );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_syntax );
- #endif
- return NULL;
- }
-
- /* return specific value */
-
- return &( e->ival );
-
- }
- #endif
-
- /***************************************************************
-
- FUNCTION: inc_esc()
-
- DESCRIPTION: This function increments the expression
- stack counter.
-
- ***************************************************************/
-
- int
- inc_esc( void )
- {
-
- #if INTENSIVE_DEBUG
- sprintf( bwb_ebuf, "in inc_esc(): prev level <%d>",
- exp_esc );
- bwb_debug ( bwb_ebuf );
- #endif
-
- ++exp_esc;
- if ( exp_esc >= ESTACKSIZE )
- {
- --exp_esc;
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in inc_esc(): Maximum expression stack exceeded <%d>",
- exp_esc );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_overflow );
- #endif
- return OP_NULL;
- }
-
- #if INTENSIVE_DEBUG
- sprintf( exp_es[ exp_esc ].string, "New Expression Stack Level %d", exp_esc );
- #endif
-
- exp_es[ exp_esc ].type = INTEGER;
- exp_es[ exp_esc ].operation = OP_NULL;
- exp_es[ exp_esc ].pos_adv = 0;
-
- return TRUE;
- }
-
- /***************************************************************
-
- FUNCTION: dec_esc()
-
- DESCRIPTION: This function decrements the expression
- stack counter.
-
- ***************************************************************/
-
- int
- dec_esc( void )
- {
- --exp_esc;
- if ( exp_esc < 0 )
- {
- exp_esc = 0;
- #if PROG_ERRORS
- sprintf( bwb_ebuf, "in dec_esc(): Expression stack counter < 0." );
- bwb_error( bwb_ebuf );
- #else
- bwb_error( err_overflow );
- #endif
- return OP_NULL;
- }
-
- return TRUE;
- }
-